<!DOCTYPE html>
<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  <title>微服务  &middot; sitename</title>
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="HandheldFriendly" content="True">
<meta name="MobileOptimized" content="320">
<meta name="viewport" content="width=device-width, initial-scale=1">


<meta name="description" content="微服务 description" />

<meta name="keywords" content="one, two, ">


<meta property="og:title" content="微服务  &middot; sitename ">
<meta property="og:site_name" content="sitename"/>
<meta property="og:url" content="https://lvzongcheng.gitee.io/%E5%BE%AE%E6%9C%8D%E5%8A%A1/%E5%BE%AE%E6%9C%8D%E5%8A%A1/" />
<meta property="og:locale" content="en-EN">


<meta property="og:type" content="article" />
<meta property="og:description" content="微服务 description"/>
<meta property="og:article:published_time" content="2017-05-13T00:00:00Z" />
<meta property="og:article:modified_time" content="2017-05-13T00:00:00Z" />

  
    
<meta property="og:article:tag" content="one">
    
<meta property="og:article:tag" content="two">
    
  

  

<script type="application/ld+json">
  {
    "@context": "http://schema.org",
    "@type": "Article",
    "headline": "微服务",
    "author": {
      "@type": "Person",
      "name": "LvZongCheng"
    },
    "datePublished": "2017-05-13",
    "description": "微服务 description",
    "wordCount":  140 
  }
</script>



<link rel="canonical" href="https://lvzongcheng.gitee.io/%E5%BE%AE%E6%9C%8D%E5%8A%A1/%E5%BE%AE%E6%9C%8D%E5%8A%A1/" />

<link rel="apple-touch-icon-precomposed" sizes="144x144" href="https://lvzongcheng.gitee.io/touch-icon-144-precomposed.png">
<link href="https://lvzongcheng.gitee.io/favicon.png" rel="icon">

<meta name="generator" content="Hugo 0.60.0" />

  <!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->

<link href='https://fonts.googleapis.com/css?family=Merriweather:300%7CRaleway%7COpen+Sans' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="/css/font-awesome.min.css">
<link rel="stylesheet" href="/css/style.css">
<link rel="stylesheet" href="/css/highlight/default.css">

  
  
	<script>
	  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
	  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
	  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
	  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

	  ga('create', 'Your Google Analytics tracking code', 'auto');
	  ga('send', 'pageview');

	</script>

</head>
<body>
  <main id="main-wrapper" class="container main_wrapper has-sidebar">
    <header id="main-header" class="container main_header">
  <div class="container brand">
  <div class="container title h1-like">
  <a class="baselink" href="https://lvzongcheng.gitee.io">
  LvZongCheng

</a>

</div>

  
<div class="container topline">
  
  淡定 执著 进取 自律


</div>


</div>

  <nav class="container nav primary no-print">
  

<a class="homelink" href="https://lvzongcheng.gitee.io">home</a>


  
<a href="https://lvzongcheng.gitee.io/framework" title="Show list of Frameworks">Frameworks</a>

<a href="https://lvzongcheng.gitee.io/java" title="Show list of Java">Java</a>

<a href="https://lvzongcheng.gitee.io/linux" title="Show list of Linux">Linux</a>

<a href="https://lvzongcheng.gitee.io/redis" title="Show list of Redis">Redis</a>

<a href="https://lvzongcheng.gitee.io/sql" title="Show list of SQL">SQL</a>

<a href="https://lvzongcheng.gitee.io/Spring" title="Show list of Spring">Spring</a>

<a href="https://lvzongcheng.gitee.io/tools" title="Show list of Tools">Tools</a>

<a href="https://lvzongcheng.gitee.io/webpage" title="Show list of WebPage">WebPage</a>

<a href="https://lvzongcheng.gitee.io/information" title="Show list of information">information</a>

<a href="https://lvzongcheng.gitee.io/network" title="Show list of network">network</a>

<a href="https://lvzongcheng.gitee.io/%E5%BE%AE%E6%9C%8D%E5%8A%A1" title="Show list of 微服务">微服务</a>

<a href="https://lvzongcheng.gitee.io/%E6%80%BB%E7%BB%93" title="Show list of 总结">总结</a>

<a href="https://lvzongcheng.gitee.io/%E6%9C%BA%E5%99%A8%E8%87%AA%E5%8A%A8%E5%8C%96" title="Show list of 机器自动化">机器自动化</a>

<a href="https://lvzongcheng.gitee.io/%E6%B1%87%E7%BC%96" title="Show list of 汇编">汇编</a>

<a href="https://lvzongcheng.gitee.io/%E8%AE%B0%E4%BA%8B%E6%9C%AC" title="Show list of 记事本">记事本</a>


</nav>

<div class="container nav secondary no-print">
  
<a id="contact-link-email" class="contact_link" rel="me" aria-label="Email" href="mailto:Lyc19880405@163.com">
  <span class="fa fa-envelope-square"></span></a>



<a id="contact-link-github" class="contact_link" rel="me" aria-label="Github" href="https://github.com/enten/hugo-boilerplate">
  <span class="fa fa-github-square"></span></a>




 


















</div>


  

</header>


<article id="main-content" class="container main_content single">
  <header class="container hat">
  <h1>微服务
</h1>

</header>

  <div class="container content">
  <h6 id="heading">开发单体式应用</h6>
<p>假设你正准备开发一款与Uber和Hailo竞争的出租车调度软件，经过初步会议和需
求分析，你可能会手动或者使用基于Rails、Spring Boot、Play或者Maven的生成
器开始这个新项目，它的六边形架构是模块化的 ，架构图如下：
<img src="/image/%E5%BE%AE%E6%9C%8D%E5%8A%A1/1.png" alt="Alt text"></p>
<p>应用核心是业务逻辑，由定义服务、域对象和事件的模块完成。围绕着核心的是与
外界打交道的适配器。适配器包括数据库访问组件、生产和处理消息的消息组件，以
及提供API或者UI访问支持的web模块等。</p>
<p>尽管也是模块化逻辑，但是最终它还是会打包并部署为单体式应用。具体的格式依赖
于应用语言和框架。例如，许多Java应用会被打包为WAR格式，部署在Tomcat或者
Jetty上，而另外一些Java应用会被打包成自包含的JAR格式，同样，Rails和Node.js
会被打包成层级目录。</p>
<p>这种应用开发风格很常见，因为IDE和其它工具都擅长开发一个简单应用，这类应用也
很易于调试，只需要简单运行此应用，用Selenium链接UI就可以完成端到端测试。单
体式应用也易于部署，只需要把打包应用拷贝到服务器端，通过在负载均衡器后端运行
多个拷贝就可以轻松实现应用扩展。在早期这类应用运行的很好。</p>
<h6 id="heading1">微处理架构——处理复杂事物</h6>
<p>许多公司，比如Amazon、eBay和NetFlix，通过采用微处理结构模式解决了上述问题。
其思路不是开发一个巨大的单体式的应用，而是将应用分解为小的、互相连接的微服务。</p>
<p>一个微服务一般完成某个特定的功能，比如下单管理、客户管理等等。每一个微服务都是
微型六角形应用，都有自己的业务逻辑和适配器。一些微服务还会发布API给其它微服务
和应用客户端使用。其它微服务完成一个Web UI，运行时，每一个实例可能是一个云VM
或者是Docker容器。</p>
<p>比如，一个前面描述系统可能的分解如下：
<img src="/image/%E5%BE%AE%E6%9C%8D%E5%8A%A1/2.png" alt="Alt text"></p>
<p>每一个应用功能区都使用微服务完成，另外，Web应用会被拆分成一系列简单的Web应用
（比如一个对乘客，一个对出租车驾驶员）。这样的拆分对于不同用户、设备和特殊应用场
景部署都更容易。</p>
<p>每一个后台服务开放一个REST API，许多服务本身也采用了其它服务提供的API。比如，驾
驶员管理使用了告知驾驶员一个潜在需求的通知服务。UI服务激活其它服务来更新Web页面。
所有服务都是采用异步的，基于消息的通讯。微服务内部机制将会在后续系列中讨论。</p>
<p>一些REST API也对乘客和驾驶员采用的移动应用开放。这些应用并不直接访问后台服务，而
是通过API Gateway来传递中间消息。API Gateway负责负载均衡、缓存、访问控制、API 计
费监控等等任务，可以通过NGINX方便实现，后续文章将会介绍到API Gateway。</p>
<h6 id="heading2">单体式应用的不足</h6>
<p>不幸的是，这种简单方法却有很大的局限性。一个简单的应用会随着时间推移逐渐变大。
在每次的sprint中，开发团队都会面对新“故事”，然后开发许多新代码。几年后，这个
小而简单的应用会变成了一个巨大的怪物。这儿有一个例子，我最近和一个开发者讨论，
他正在写一个工具，用来分析他们一个拥有数百万行代码的应用中JAR文件之间的依赖关
系。我很确信这个代码正是很多开发者经过多年努力开发出来的一个怪物。</p>
<p>一旦你的应用变成一个又大又复杂的怪物，那开发团队肯定很痛苦。敏捷开发和部署举步
维艰，其中最主要问题就是这个应用太复杂，以至于任何单个开发者都不可能搞懂它。因
此，修正bug和正确的添加新功能变的非常困难，并且很耗时。另外，团队士气也会走下
坡路。如果代码难于理解，就不可能被正确的修改。最终会走向巨大的、不可理解的泥潭。</p>
<p>单体式应用也会降低开发速度。应用越大，启动时间会越长。比如，最近的一个调查表明，
有时候应用的启动时间居然超过了12分钟。我还听说某些应用需要40分钟启动时间。如果
开发者需要经常重启应用，那么大部分时间就要在等待中渡过，生产效率受到极大影响。</p>
<p>另外，复杂而巨大的单体式应用也不利于持续性开发。今天，SaaS应用常态就是每天会改
变很多次，而这对于单体式应用模式非常困难。另外，这种变化带来的影响并没有很好的
被理解，所以不得不做很多手工测试。那么接下来，持续部署也会很艰难。</p>
<p>单体式应用在不同模块发生资源冲突时，扩展将会非常困难。比如，一个模块完成一个CPU
敏感逻辑，应该部署在AWS EC2 Compute Optimized instances，而另外一个内存数据
库模块更合适于EC2 Memory-optimized instances。然而，由于这些模块部署在一起，
因此不得不在硬件选择上做一个妥协。</p>
<p>单体式应用另外一个问题是可靠性。因为所有模块都运行在一个进程中，任何一个模块中的
一个bug，比如内存泄露，将会有可能弄垮整个进程。除此之外，因为所有应用实例都是唯
一的，这个bug将会影响到整个应用的可靠性。</p>
<p>最后，单体式应用使得采用新架构和语言非常困难。比如，设想你有两百万行采用XYZ框架
写的代码。如果想改成ABC框架，无论是时间还是成本都是非常昂贵的，即使ABC框架更好。
因此，这是一个无法逾越的鸿沟。你不得不在最初选择面前低头。</p>
<p>总结一下：一开始你有一个很成功的关键业务应用，后来就变成了一个巨大的，无法理解的
怪物。因为采用过时的，效率低的技术，使得雇佣有潜力的开发者很困难。应用无法扩展，
可靠性很低，最终，敏捷性开发和部署变的无法完成。</p>
<h6 id="heading3">微服务架构的好处</h6>
<p>首先，通过分解巨大单体式应用为多个服务方法解决
了复杂性问题。在功能不变的情况下，应用被分解为多个可管理的分支或服务。每
个服务都有一个用RPC-或者消息驱动API定义清楚的边界。微服务架构模式给采用
单体式编码方式很难实现的功能提供了模块化的解决方案，由此，单个服务很容易
开发、理解和维护。</p>
<p>第二，这种架构使得每个服务都可以有专门开发团队来开发。开发者可以自由选择
开发技术，提供API服务。当然，许多公司试图避免混乱，只提供某些技术选择。然
后，这种自由意味着开发者不需要被迫使用某项目开始时采用的过时技术，他们可
以选择现在的技术。甚至于，因为服务都是相对简单，即使用现在技术重写以前代
码也不是很困难的事情。</p>
<p>第三，微服务架构模式是每个微服务独立的部署。开发者不再需要协调其它服务部
署对本服务的影响。这种改变可以加快部署速度。UI团队可以采用AB测试，快速的
部署变化。微服务架构模式使得持续化部署成为可能。</p>
<p>最后，微服务架构模式使得每个服务独立扩展。你可以根据每个服务的规模来部署
满足需求的规模。甚至于，你可以使用更适合于服务资源需求的硬件。比如，你可
以在EC2 Compute Optimized instances上部署CPU敏感的服务，而在
EC2 memory-optimized instances上部署内存数据库。</p>
<h6 id="heading4">微服务架构的不足</h6>
<p>微服务的目的是有效的拆分应用，实现敏捷开发和部署。</p>
<p>另外一个主要的不足是，微服务应用是分布式系统，由此会带来固有的复杂性。开
发者需要在RPC或者消息传递之间选择并完成进程间通讯机制。更甚于，他们必须
写代码来处理消息传递中速度过慢或者不可用等局部失效问题。当然这并不是什么
难事，但相对于单体式应用中通过语言层级的方法或者进程调用，微服务下这种技
术显得更复杂一些。</p>
<p>另外一个关于微服务的挑战来自于分区的数据库架构。商业交易中同时给多个业务
分主体更新消息很普遍。这种交易对于单体式应用来说很容易，因为只有一个数据
库。在微服务架构应用中，需要更新不同服务所使用的不同的数据库。使用分布式
交易并不一定是好的选择，不仅仅是因为CAP理论，还因为今天高扩展性的NoSQL
数据库和消息传递中间件并不支持这一需求。最终你不得不使用一个最终一致性的
方法，从而对开发者提出了更高的要求和挑战。</p>
<p>测试一个基于微服务架构的应用也是很复杂的任务。比如，采用流行的Spring Boot
架构，对一个单体式web应用，测试它的REST API，是很容易的事情。反过来，同
样的服务测试需要启动和它有关的所有服务（至少需要这些服务的stubs）。再重申
一次，不能低估了采用微服务架构带来的复杂性。</p>
<p>另外一个挑战在于，微服务架构模式应用的改变将会波及多个服务。比如，假设你在
完成一个案例，需要修改服务A、B、C，而A依赖B，B依赖C。在单体式应用中，你
只需要改变相关模块，整合变化，部署就好了。对比之下，微服务架构模式就需要考
虑相关改变对不同服务的影响。比如，你需要更新服务C，然后是B，最后才是A，幸
运的是，许多改变一般只影响一个服务，而需要协调多服务的改变很少。</p>
<p>部署一个微服务应用也很复杂，一个分布式应用只需要简单在复杂均衡器后面部署各
自的服务器就好了。每个应用实例是需要配置诸如数据库和消息中间件等基础服务。
相对比，一个微服务应用一般由大批服务构成。例如，根据Adrian Cockcroft，Hailo
有160个不同服务构成，NetFlix有大约600个服务。每个服务都有多个实例。这就造
成许多需要配置、部署、扩展和监控的部分，除此之外，你还需要完成一个服务发现
机制（后续文章中发表），以用来发现与它通讯服务的地址（包括服务器地址和端口）。
传统的解决问题办法不能用于解决这么复杂的问题。接续而来，成功部署一个微服务
应用需要开发者有足够的控制部署方法，并高度自动化。</p>
<p>一种自动化方法是使用PaaS服务，例如Cloud Foundry。PaaS给开发者提供一个部署
和管理微服务的简单方法，它把所有这些问题都打包内置解决了。同时，配置PaaS的
系统和网络专家可以采用最佳实践和策略来简化这些问题。另外一个自动部署微服务
应用的方法是开发对于你来说最基础的PaaS系统。一个典型的开始点是使用一个集群
化方案，比如配合Docker使用Mesos或者Kubernetes。后面的系列我们会看看如何
基于软件部署方法例如NGINX，可以方便的在微服务层面提供缓存、权限控制、API
统计和监控。</p>

</div>


  
</article>
      <footer id="main-footer" class="container main_footer">
  

  <div class="container nav foot no-print">
  
<a href="https://lvzongcheng.gitee.io/license">license</a>


  <a class="toplink" href="#">back to top</a>

</div>

  <div class="container credits">
  
<div class="container footline">
  
  code with <!-- raw HTML omitted --><!-- raw HTML omitted -->


</div>


  
<div class="container copyright">
  
  (c) 2015 yourname.


</div>


</div>

</footer>

    </main>
    
<script type="text/javascript">
  (function() {
    
    
    if (window.location.hostname == "localhost")
      return;
    var dsq = document.createElement('script'); dsq.async = true; dsq.type = 'text/javascript';
    dsq.src = '//your_disqus_shortname.disqus.com/count.js';
    (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
  })();
</script>



<script src="/js/highlight.pack.js"></script>
<script>hljs.initHighlightingOnLoad();</script>



    
  </body>
</html>

